package fun.easycode.webterminal.adapter.socket;

import com.fasterxml.jackson.core.type.TypeReference;
import fun.easycode.webterminal.common.util.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.Objects;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
public class TerminalSocketHandler extends AbstractWebSocketHandler {

    private final ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 60
            , java.util.concurrent.TimeUnit.SECONDS, new java.util.concurrent.LinkedBlockingQueue<>());


    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 设置文本消息的大小限制（字节）10m
        session.setTextMessageSizeLimit(10485760);
        // 设置二进制消息的大小限制（字节） 10m
        session.setBinaryMessageSizeLimit(10485760);

        UriComponents uriComponents = UriComponentsBuilder.fromUri(Objects.requireNonNull(session.getUri())).build();

        String id = uriComponents.getQueryParams().get("id").stream().findFirst().orElse("");

        if (StringUtils.isEmpty(id)) {
            session.sendMessage(new TextMessage("ERROR：请传入主机ID。"));
            return;
        }


        Terminal terminal = new Terminal(id, session, executor);

        session.getAttributes().put("terminal", terminal);

        terminal.connect();

    }

    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {

        Terminal terminal = (Terminal) session.getAttributes().get("terminal");

        terminal.send(message.getPayload().array());
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//        System.err.println("handleTextMessage => " + message.getPayload());

        String messagePayload = message.getPayload();

        MessageContent content = JacksonUtil.readValue(messagePayload, new TypeReference<>() {
        });

        Terminal terminal = (Terminal) session.getAttributes().get("terminal");
        terminal.send(content);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.info("handleTransportError => ", exception);
        closeJschSession(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        log.info("afterConnectionClosed => {} ", closeStatus);
        closeJschSession(session);
    }

    private void closeJschSession(WebSocketSession session) {
        log.info("closeJschSession");

        Terminal terminal = (Terminal) session.getAttributes().get("terminal");
        terminal.disconnect();
    }

}
